#include <cxxomfort/cxxomfort.hpp>
#include <cxxomfort/library/type_name.hpp>
#include <cxxomfort/string.hpp>
#include "../library/affixes/string.hpp"
#include <iostream>

// reference: 
// https://en.cppreference.com/w/cpp/language/user_literal


template <typename T>
void show (std::ostream& os, T const& t) {
	using namespace std;
	using cxxomfort::library::type_name;
	os<< "[type:"<< type_name<T>();
	os<< " sizeof:"<< sizeof(T);
	os<< " value:'"<< t<< "' ] "<< endl;
	
}

template<> void show (std::ostream& os, std::wstring const& t) {
	using namespace std;
	using cxxomfort::library::type_name;
	string T= type_name<wstring const>();
	os<< "[type:"<< T.c_str();
	os<< " sizeof:"<< sizeof(T);
	os<< " value:'"<< string(t.begin(), t.end())<< "' ] "<< endl;
	
}

int main () {
	using namespace std;
	using namespace cxxomfort::library::string::literals;
	using cxxomfort::library::type_name;
	cout<< "In C++ the type of a string literal is const char[N].\n"<< endl;
#if (CXXOMFORT_CXX_STD>=2011)
	auto foo = "Hello World";
	cout<< "Type of string literal: "<< type_name<decltype(foo)>()<< " ; "<< typeid(foo).name()<< endl;
	cout<< "       passed directly: "<< type_name<decltype("Hello World")>()<< " ; "<< typeid("Hello World").name()<< endl;
#endif
	cout<< "\n 1 - Using as suffixes: value | foo "<< endl;
	cout<< "With \"chars...\" : "; show(cout, "Hello World1"); // should be: const char[]
	cout<< "With std::string  : "; show(cout, "Hello World2" | s); // should be: std::string
	cout<< "With std::wstring : "; show(cout, L"Hello World3" | s); 
	cout<< "With AESTHETICS   : "; show(cout, "~*Hello World*~ ^_^ " | aesth);
	cout<< endl;

	// cool thing: they also work as normal functions (function objects)
	cout<< "\n 2 - Using as function objects: foo ( value ) "<< endl;
	cout<< "Expecting string 5    : "<< flush; show(cout, s("Hello World5")); // should be: std::string
	cout<< "Expecting AESTHETIC   : "<< flush; show(cout, aesth("Hello World6")); 
	
	cout<< endl;
	
	// and in C++11 onwards, as literal suffixes
#if (CXXOMFORT_CXX_STD >= 2011)
	cout<< "\n 3 - Using as C++11 suffixes: value_foo "<< endl;
    cout<< "Expecting string  4   : "; show(cout, "Hello World4"_s); // should be: std::string
    cout<< "Expecting wstring 5   : "; show(cout, L"Hello World5"_s);
#endif

}
